package com.suduku.calc;

import com.suduku.entity.Box;
import com.suduku.util.SudoUtil;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 与XY-wing对应 <br/>
 * 测试数据：SudoUtil.transpose(DataConstant.OTHER_XY_WING_01) 转置后的数独
 */
public class YXwingCalc extends AbstractCalc {

    @Override
    Box solve() {
        Set<Map.Entry<Integer, List<Box>>> entries = getYMap().entrySet();
        // 遍历所有的列
        for(Map.Entry<Integer, List<Box>> entry : entries) {
            // 当前列
            List<Box> list = entry.getValue();
            // 遍历当前行所有的单元格
            for (Box b1 : list) {
                // 获取B1格，只能有两个候选数字
                if(b1.isBlank() && b1.getCList().size() == 2) {
                    // 遍历B2单元格
                    for (Box b2 : list) {
                        // B2不能与B1在同一宫内，并且也只有两个候选数字，并且两个候选数字与B1不能完全相同
                        if(b2.isBlank() && b2.getG() != b1.getG() && b2.getCList().size() == 2 && !SudoUtil.isEqTwoList(b1.getCList(), b2.getCList())) {
                            // 确定数字x，为B1和B2中相同的数字
                            Integer x = SudoUtil.getEqContent(b1.getCList(), b2.getCList());
                            if(x != null) {
                                // 从B1中获取数字y，从B2中获取数字z
                                Integer y = SudoUtil.getOther(b1.getCList(), x);
                                Integer z = SudoUtil.getOther(b2.getCList(), x);
                                // 从B1所在宫内，获取根据数字y和z获取单元格B3，B3不能与B1在同一列
                                List<Box> b3List = getGList(b1).stream()
                                        .filter(b -> b.isBlank() && b.getI() != b1.getI() && b.getY() != b1.getY()
                                                && b.getCList().size() == 2
                                                && b.getCList().containsAll(Arrays.asList(y, z)))
                                        .collect(Collectors.toList());
                                if(b3List.size() == 1) {
                                    // 如果存在B3单元格，则可以排除B2所在宫与B3所在列中，包含z的候选数字
                                    List<Box> clearList = getYList(b3List.get(0)).stream()
                                            .filter(b -> b.getG() == b2.getG() && b.isBlank() && b.getCList().contains(z))
                                            .collect(Collectors.toList());
                                    for(Box box : clearList) {
                                        box.removeCList(z);
                                        change(box, SudoUtil.getList(b1, b2, b3List.get(0)), z);
                                        return box;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

}
